﻿using System.Collections.Generic;
using System.Linq;

namespace Sidvall.Security
{
    public class ClaimCollection : System.Collections.ObjectModel.Collection<Claim>
    {
        #region Public Members

        #region Add

        public void Add(string claimType, string value)
        {
            Add(claimType, value, null);
        }
        public void Add(string claimType, string value, string valueType)
        {
            var item = new Claim()
            {
                ClaimType = claimType,
                Value = value,
                ValueType = valueType,
            };
            Add(item);
        }

        #endregion
        #region AddRange

        public void AddRange(IEnumerable<Claim> items)
        {
            if (items == null)
                return;
            foreach (var item in items)
            {
                if (item != null)
                    Add(item);
            }
        }

        #endregion
        #region FindClaim

        public Claim FindClaim(string claimType)
        {
            if (!string.IsNullOrWhiteSpace(claimType))
            {
                return (from o in this
                        where o.ClaimType.Equals(claimType, System.StringComparison.OrdinalIgnoreCase)
                        select o).FirstOrDefault();
            }
            else
            {
                return this.FirstOrDefault();
            }
        }
        public Claim FindClaim(string claimType, string value)
        {
            return (from o in this
                    where o.Equals(claimType, value)
                    select o).FirstOrDefault();
        }

        #endregion
        #region FindClaims

        public ClaimCollection FindClaims(string claimType)
        {
            ClaimCollection items;
            IEnumerable<Claim> claims;

            if (!string.IsNullOrWhiteSpace(claimType))
            {
                claims = (from o in this
                          where o.ClaimType.Equals(claimType, System.StringComparison.OrdinalIgnoreCase)
                          select o);
                items = new ClaimCollection();
                items.AddRange(claims);
                return items;
            }
            else
            {
                return this;
            }
        }

        #endregion
        #region GetValue

        public string GetValue(string claimType, string defaultValue)
        {
            var item = FindClaim(claimType);
            if (item != null)
                return item.Value;
            return defaultValue;
        }

        #endregion
        #region HasClaim

        public bool HasClaim(string claimType, string value)
        {
            return (from o in this
                    where o.Equals(claimType, value)
                    select o).Any();
        }

        #endregion
        #region Merge

        public void Merge(IEnumerable<Claim> items)
        {
            Claim existingItem;

            if (items == null)
                return;
            foreach (var item in items)
            {
                existingItem = FindClaim(item.ClaimType, item.Value);
                if (existingItem == null)
                    Add(item);
            }
        }

        #endregion
        #region RemoveClaim

        public bool RemoveClaim(Claim claim)
        {
            Claim item;
            int iMax;

            if (claim == null)
                return false;
            iMax = this.Count;
            for (int i = iMax - 1; i >= 0; i--)
            {
                item = this[i];
                if (claim.Equals(item))
                    return Remove(item);
            }
            return false;
        }

        #endregion
        #region RemoveClaims

        public void RemoveClaims(IEnumerable<Claim> claims)
        {
            if (claims == null)
                return;
            foreach (var claim in claims)
                RemoveClaim(claim);
        }

        #endregion

        #region Deserialize

        public static ClaimCollection Deserialize(string value)
        {
            return Deserialize(value, null);
        }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public static ClaimCollection Deserialize(string value, ClaimCollection defaultValue)
        {
            return Sidvall.Serialization.SerializerManager.Current.TryDeserialize<ClaimCollection>(value, () =>
            {
                return defaultValue;
            });
        }

        #endregion
        #region Serialize

        public string Serialize()
        {
            return Serialize(this);
        }
        public static string Serialize(ClaimCollection item)
        {
            return Sidvall.Serialization.SerializerManager.Current.SerializeObject(item);
        }

        #endregion

        #endregion
        #region Constructors

        public ClaimCollection()
        {
        }

        #endregion
    }
}
